package cn.hamster3.mc.plugin.core.bukkit;

import cn.hamster3.mc.plugin.core.bukkit.api.CoreBukkitAPI;
import cn.hamster3.mc.plugin.core.bukkit.command.core.CoreCommand;
import cn.hamster3.mc.plugin.core.bukkit.command.lore.LoreCommand;
import cn.hamster3.mc.plugin.core.bukkit.command.nbt.NBTCommand;
import cn.hamster3.mc.plugin.core.bukkit.constant.CoreMessage;
import cn.hamster3.mc.plugin.core.bukkit.hook.PointAPI;
import cn.hamster3.mc.plugin.core.bukkit.hook.VaultAPI;
import cn.hamster3.mc.plugin.core.bukkit.listener.CallbackListener;
import cn.hamster3.mc.plugin.core.bukkit.listener.DebugListener;
import cn.hamster3.mc.plugin.core.bukkit.page.handler.PageHandler;
import cn.hamster3.mc.plugin.core.bukkit.page.listener.PageListener;
import cn.hamster3.mc.plugin.core.bukkit.util.MinecraftVersion;
import cn.hamster3.mc.plugin.core.common.api.CoreAPI;
import cn.hamster3.mc.plugin.core.common.config.YamlConfig;
import cn.hamster3.mc.plugin.core.common.util.UpdateCheckUtils;
import lombok.Getter;
import net.kyori.adventure.platform.bukkit.BukkitAudiences;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.InventoryView;
import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.java.JavaPlugin;
import org.bukkit.scheduler.BukkitTask;
import org.jetbrains.annotations.NotNull;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.StandardCopyOption;
import java.util.logging.Logger;

@SuppressWarnings("CallToPrintStackTrace")
public class HamsterCorePlugin extends JavaPlugin {
    @Getter
    private static HamsterCorePlugin instance;
    @Getter
    private BukkitAudiences audienceProvider;

    /**
     * 在服务器主线程上执行一个任务
     *
     * @param runnable 任务内容
     * @return 任务实例
     */
    @SuppressWarnings("UnusedReturnValue")
    public static BukkitTask sync(@NotNull Runnable runnable) {
        return Bukkit.getScheduler().runTask(instance, runnable);
    }

    /**
     * 在服务器主线程外异步执行一个任务
     *
     * @param runnable 任务内容
     * @return 任务实例
     */
    @SuppressWarnings("UnusedReturnValue")
    public static BukkitTask async(@NotNull Runnable runnable) {
        return Bukkit.getScheduler().runTaskAsynchronously(instance, runnable);
    }

    @Override
    public void onLoad() {
        instance = this;
        long start = System.currentTimeMillis();
        Logger logger = getLogger();
        logger.info("仓鼠核心正在初始化");
        logger.info("Minecraft 版本: " + MinecraftVersion.getMCVersion());
        logger.info("NMS 版本: " + MinecraftVersion.getNMSVersion());
        try {
            File dataFolder = getDataFolder();
            if (dataFolder.mkdir()) {
                logger.info("已生成插件存档文件夹");
            }
            File configFile = new File(dataFolder, "config.yml");
            if (!configFile.exists()) {
                try (InputStream stream = getResource("config.yml")) {
                    if (stream != null) {
                        Files.copy(stream, configFile.toPath(), StandardCopyOption.REPLACE_EXISTING);
                    }
                }
            }
            CoreBukkitAPI.init(configFile);
            logger.info("已初始化 CoreAPI");
        } catch (Exception e) {
            logger.warning("初始化 CoreAPI 出错");
            e.printStackTrace();
        }
        CoreMessage.init(this);
        logger.info("已初始化语言文本");
        long time = System.currentTimeMillis() - start;
        logger.info("仓鼠核心初始化完成，总计耗时 " + time + " ms");
    }

    @Override
    public void onEnable() {
        long start = System.currentTimeMillis();
        Logger logger = getLogger();
        logger.info("仓鼠核心正在启动");
        audienceProvider = BukkitAudiences.create(this);
        logger.info("已创建 AudienceProvider");
        CoreCommand.INSTANCE.register();
        LoreCommand.INSTANCE.register();
        NBTCommand.INSTANCE.register();
        Bukkit.getPluginManager().registerEvents(PageListener.INSTANCE, this);
        logger.info("已注册 PageListener");
        Bukkit.getPluginManager().registerEvents(CallbackListener.INSTANCE, this);
        logger.info("已注册 CallbackListener");
        Bukkit.getPluginManager().registerEvents(DebugListener.INSTANCE, this);
        logger.info("已注册 DebugListener");
        long time = System.currentTimeMillis() - start;
        sync(() -> {
            PointAPI.reloadPlayerPointAPIHook();
            VaultAPI.reloadVaultHook();
            async(() -> {
                for (Plugin plugin : Bukkit.getPluginManager().getPlugins()) {
                    try (InputStream stream = plugin.getResource("update.yml")) {
                        if (stream == null) {
                            continue;
                        }
                        try (InputStreamReader reader = new InputStreamReader(stream, StandardCharsets.UTF_8)) {
                            YamlConfig config = YamlConfig.load(reader);
                            UpdateCheckUtils.showUpdate(plugin.getName(), config, Bukkit.getConsoleSender()::sendMessage);
                        }
                    } catch (IOException ignored) {
                    }
                }
            });

        });
        logger.info("仓鼠核心启动完成，总计耗时 " + time + " ms");
    }

    @Override
    public void onDisable() {
        long start = System.currentTimeMillis();
        Logger logger = getLogger();
        CoreAPI.getInstance().getJedisPool().close();
        logger.info("已关闭 Redis 连接池");
        CoreAPI.getInstance().getHikariDataSource().close();
        logger.info("已关闭数据库连接池");
        CoreAPI.getInstance().getExecutorService().shutdownNow();
        logger.info("已关闭 ExecutorService 线程池");
        CoreAPI.getInstance().getScheduledService().shutdownNow();
        logger.info("已关闭 ScheduledExecutorService 线程池");
        for (Player player : Bukkit.getOnlinePlayers()) {
            InventoryView view = player.getOpenInventory();
            Inventory inventory = view.getTopInventory();
            if (!(inventory.getHolder() instanceof PageHandler)) {
                continue;
            }
            player.closeInventory();
        }
        logger.info("已关闭所有玩家的界面");
        long time = System.currentTimeMillis() - start;
        logger.info("仓鼠核心已关闭，总计耗时 " + time + " ms");
    }
}
